#![cfg_attr(
    all(not(debug_assertions), target_os = "windows"),
    windows_subsystem = "windows"
)]

use std::fs::File;
use std::io::prelude::*;

use serde_json::{json, Value};
use tracing::{error, info};

const RESEARCH_RUL: &str = "https://www.douyu.com/japi/search/api/getSearchRec";
const H5_PLAY_URL: &str = "https://www.douyu.com/lapi/live/getH5Play";
const DB: &str = "broadcast.db";

fn main() {
    tracing_subscriber::fmt::init();
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![
            get_search_rec,
            get_h5_play_url,
            put,
            get,
        ])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

#[tauri::command]
async fn get_search_rec(kw: String) -> String {
    info!("{}?kw={}", RESEARCH_RUL, kw);
    let resp = reqwest::get(format!("{}?kw={}", RESEARCH_RUL, kw))
        .await
        .unwrap();
    match resp.text().await {
        Ok(text) => {
            info!("{}", text);
            text
        }
        Err(e) => {
            error!("{}", e);
            String::new()
        }
    }
}
#[tauri::command]
async fn get_h5_play_url(id: usize, body: String) -> String {
    info!("{}/{},{}", H5_PLAY_URL, id, body);
    let resp = reqwest::Client::new()
        .post(format!("{}/{}", H5_PLAY_URL, id))
        .header("content-type", "application/x-www-form-urlencoded")
        .body(body)
        .send()
        .await
        .unwrap();
    match resp.text().await {
        Ok(text) => {
            info!("{}", text);
            let json: Value = serde_json::from_str(&text).unwrap();
            let data = &json["data"];
            match data {
                Value::Object(obj) => {
                    format!(
                        "{}/{}",
                        obj["rtmp_url"].as_str().unwrap(),
                        obj["rtmp_live"].as_str().unwrap()
                    )
                }
                _ => String::new(),
            }
        }
        Err(e) => {
            error!("{}", e);
            String::new()
        }
    }
}

#[tauri::command]
fn put(key: String, value: String) {
    let mut file = File::options()
        .read(true)
        .write(true)
        .create(true)
        .truncate(false)
        .open(DB)
        .unwrap();
    let mut contents = String::new();
    file.read_to_string(&mut contents).unwrap();
    let mut map: Value = serde_json::from_str(&contents).unwrap_or(json!({}));
    match map.get_mut(key.clone()) {
        Some(v) => {
            *v = json!(value);
        }
        None => {
            map = json!({ key: value });
        }
    }
    let mut file = File::options()
        .read(true)
        .write(true)
        .create(true)
        .truncate(true)
        .open(DB)
        .unwrap();
    file.write_all(serde_json::to_string(&map).unwrap().as_bytes())
        .unwrap();
}

#[tauri::command]
fn get(key: String) -> String {
    let mut file = File::options()
        .read(true)
        .write(true)
        .create(true)
        .truncate(false)
        .open(DB)
        .unwrap();
    let mut contents = String::new();
    file.read_to_string(&mut contents).unwrap();
    let map: Value = serde_json::from_str(&contents).unwrap_or(json!({}));
    map[key].as_str().unwrap_or("").to_string()
}
